/*
 * ---------------------------------------------------------------------------------------------------------------------------------------------------*
 * SBS Priceboard V2.0
 * Copyright (C) 2008 Unicom Vietnam JSC
 * ---------------------------------------------------------------------------------------------------------------------------------------------------*
 * HeadURL: http://192.168.1.4/svn/priceboard/trunk/SBS_PriceboardV2/front-end/end-user/ipriceboard/src/com/unicom/priceboard/thread/HaStockThread.java
 * LastChangeBy: quanhm
 * LastChangeDate: Aug 6 2008
 */
package com.unicom.priceboard.thread;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.unicom.priceboard.data.hastc.BestPriceParser;
import com.unicom.priceboard.data.hastc.HaIndexParser;
import com.unicom.priceboard.data.hastc.HaStockParser;
import com.unicom.priceboard.data.vo.HaIndex;
import com.unicom.priceboard.data.vo.HaStock;
import com.unicom.priceboard.util.Constants;
import com.unicom.priceboard.util.DataPath;
import com.unicom.priceboard.util.MarketStateUtil;

/**
 * Creation date: Jul 17, 2008
 * @author quan
 */
public class HaStockThread implements Runnable {
	private static final Log logger = LogFactory.getLog(HaStockThread.class);
	public volatile static HashMap<String, HaStock> currentStockList = new HashMap<String, HaStock>();
	public volatile static HashMap<String, HaIndex> mapMarketIndex = new HashMap<String, HaIndex>();

	private static int wait = 1;

	//lastest time of reading zip file
	private long lastRead = 0;

	//flag for reseting data
	private boolean flagReset=true;

	//path to zip file
	String zipFilePath = "";

	//Current trading session
	public static String session="1";

	public HaStockThread() {
//		wait = Integer.parseInt(Resources.getConfigMessage("priceboard.hastc.wait"));
		wait = Integer.parseInt(DataPath.hastcWait);
	}

	public void run() {
		while(true) {
			ZipFile zf = null;
			try {
				
//				this.zipFilePath = Resources.getConfigMessage("priceboard.file.hastc.path");
				this.zipFilePath = DataPath.zipFilePath;
				
				File f = new File(zipFilePath);
				if (currentStockList.isEmpty()) {
					zf = new ZipFile(f, ZipFile.OPEN_READ);

					//Parsing STS_MarketInfo.XML
					ZipEntry marketEntry = zf.getEntry(Constants.MARKET_INFO_ENTRY);
					InputStream marketStream = zf.getInputStream(marketEntry);
					HaIndexParser marketParser = new HaIndexParser();
					marketParser.parseDocument(marketStream);

					//parsing STS_TOP3_PRICE_A.XML
					ZipEntry bestPriceEntry = zf.getEntry(Constants.BEST_PRICE_ENTRY);
					InputStream bestPriceStream = zf.getInputStream(bestPriceEntry);
					BestPriceParser bPriceParser = new BestPriceParser();
					bPriceParser.parseDocument(bestPriceStream);

					//Reading STS_StocksInfo.XML
					ZipEntry stockEntry = zf.getEntry(Constants.STOCK_INFO_ENTRY);
					InputStream stockStream = zf.getInputStream(stockEntry);
					HaStockParser parser = new HaStockParser();
					parser.parseDocument(stockStream);
					lastRead = f.lastModified();
				} else if (isReady(new File(zipFilePath)) && f.canRead() && f.length()>0) {
					//Only read if there is a new file
					zf = new ZipFile(f, ZipFile.OPEN_READ);

					//Parsing STS_MarketInfo.XML
					ZipEntry marketEntry = zf.getEntry(Constants.MARKET_INFO_ENTRY);
					InputStream marketStream = zf.getInputStream(marketEntry);
					HaIndexParser marketParser = new HaIndexParser();
					marketParser.parseDocument(marketStream);

					//parsing STS_TOP3_PRICE_A.XML
					ZipEntry bestPriceEntry = zf.getEntry(Constants.BEST_PRICE_ENTRY);
					InputStream bestPriceStream = zf.getInputStream(bestPriceEntry);
					BestPriceParser bPriceParser = new BestPriceParser();
					bPriceParser.parseDocument(bestPriceStream);

					//Reading STS_StocksInfo.XML
					ZipEntry stockEntry = zf.getEntry(Constants.STOCK_INFO_ENTRY);
					InputStream stockStream = zf.getInputStream(stockEntry);
					HaStockParser parser = new HaStockParser();
					parser.parseDocument(stockStream);
				}
			}catch (ZipException ze) {
//				ze.printStackTrace();
				logger.error("Zip file error:"+ze.getMessage());
			}catch (IOException ie) {
				logger.error("***** IO Exception: " + ie.getMessage());
//				ie.printStackTrace();
			}catch (Exception e) { // Make sure no exception throws
//				e.printStackTrace();
				logger.error("Error with STS_Info_Public.zip: "+e.getMessage());
			}finally {
				if (zf != null) {
					try {
						zf.close();
					} catch (IOException e) {
						logger.error("Cannot close zip file due to : "+ e.getMessage());
					}
				}
			}

			try {
				Thread.sleep(1000*wait);
			} catch (Exception e) {
				logger.debug("Exception: " + e.getMessage());
			}
		}
	}

	/**
	 * @return a String with "," separator
	 */
	public static String getStockList()	{
		StringBuffer retString = new StringBuffer("");
		List<String> sortList = new ArrayList<String>();

		sortList.addAll(currentStockList.keySet());
		Collections.sort(sortList);

		for(int i=0;i<sortList.size();i++){
			if(i<sortList.size()-1)
				retString.append(sortList.get(i)+",");
			else
				retString.append(sortList.get(i));
		}

		return retString.toString();
	}

	/**
	 * @param symbol
	 * @return a stock of HASTC market
	 */
	public static HaStock getStock(String symbol) {
		return currentStockList.get(symbol);
	}

	/**
	 * @return current HASTC-Index
	 */
	public static HaIndex getCurrentIndex() {
		//DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		//String today = df.format(new Date(System.currentTimeMillis()));
		//String []arrDay = today.split("-");
//		String dateFile=gettimeFile(Resources.getConfigMessage("priceboard.file.hastc.path"));
		String dateFile=gettimeFile(DataPath.zipFilePath);
		String []arrDay = dateFile.split("/");
		String reformat_day = arrDay[2]+"/"+arrDay[1]+"/"+arrDay[0];
		HaIndex currentIndex = mapMarketIndex.get(reformat_day);

		//if today is not a trading day then we get the nearest Index
		if(mapMarketIndex.size()==0){
			currentIndex=new HaIndex();
			currentIndex.setChangeIndex(0);
			currentIndex.setIndex(0);
			currentIndex.setPtTotalVal(0);
			currentIndex.setPtTotalVol(0);
			currentIndex.setToPreviousDay(reformat_day);
			currentIndex.setPctIndex(0);
			currentIndex.setTotalTrade("0");
			currentIndex.setCenterId(2);
			currentIndex.setTotalVal(0);
			currentIndex.setTotalVol("0");
			currentIndex.setIndexDate(reformat_day);
//			int newSession=Integer.parseInt(session)+1;
			currentIndex.setSession("");
//			session="";
		}else if(currentIndex==null){//getting the previous HASTC-Index
			currentIndex = mapMarketIndex.values().iterator().next();
		}
		return currentIndex;
	}

	private static String gettimeFile(String path){
		File checktime =new File(path);
		long current_time=checktime.lastModified();
	    Date lastday=new Date(current_time);
	    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
		String timeFile =dateFormat.format(lastday);
		return timeFile.replaceAll("-", "/");

	}
	/**
	 * @param f file to check
	 * @return true if file is newer, otherwise false
	 */
	private boolean isReady(File f) {
		long currentRead = f.lastModified();
		if (currentRead > lastRead) {
			if (MarketStateUtil.getHastcState().equals("2")) {
				BestPriceParser.resetBestPrice();
				resetIndex();
				flagReset = true;
			}
			lastRead = currentRead;
			return true;
		}else if (TimerThread.CURRENT_TIME>Constants.TIME_RESET_FLAG_HASTC && flagReset==true)
			flagReset = false;

		return false;
	}

	/**
	 * reset data for new day
	 * @return
	 */
	private void resetIndex(){
		mapMarketIndex.clear();
	}
}
